import string
import random
from datetime import datetime

def generate_id(prefix: str, length: int = 8) -> str:
    """
    生成唯一ID(支持用户、课程、作业等对象的唯一标识)
    功能:按前缀+随机字符组合生成ID,确保系统内对象标识不重复,符合项目模块化数据管理需求
    参数:
        prefix: ID前缀(如"USER_"对应用户、"COURSE_"对应课程、"ASSIGN_"对应作业)
        length: 随机字符部分长度(默认8位)
    返回:
        str: 完整唯一ID(如"USER_3a7f9d2b")
    """
    # 随机字符池:包含大小写字母+数字,避免易混淆字符(如O、0、I、1)
    valid_chars = string.ascii_letters + string.digits
    valid_chars = valid_chars.replace("O", "").replace("0", "").replace("I", "").replace("1", "")
    # 生成随机字符段
    random_part = ''.join(random.choice(valid_chars) for _ in range(length))
    # 拼接前缀与随机段,返回最终ID
    return f"{prefix}{random_part}"


def input_validation(input_value: str, input_type: str) -> bool:
    """
    输入验证工具(确保用户输入符合系统规范,避免非法数据录入)
    功能:针对不同类型的输入(用户名、密码、邮箱、课程名等)制定验证规则,符合项目"实现 proper error handling and input validation"的技术要求
    参数:
        input_value: 待验证的输入字符串
        input_type: 输入类型(支持"username"/"password"/"email"/"course_name"/"assignment_title")
    返回:
        bool: 验证通过返回True,失败返回False
    """
    if not isinstance(input_value, str) or len(input_value.strip()) == 0:
        return False  # 空字符串直接判定为无效
    
    input_value = input_value.strip()
    if input_type == "username":
        # 用户名规则:3-15位,仅包含字母、数字、下划线,且不能以数字开头
        if not (3 <= len(input_value) <= 15) or input_value[0].isdigit():
            return False
        # 允许字母、数字、下划线
        return all(c.isalnum() or c == '_' for c in input_value)
    elif input_type == "password":
        # 密码规则:6-20位,至少包含1个小写字母、1个数字(放宽要求,允许纯小写字母+数字)
        has_lower = any(c.islower() for c in input_value)
        has_digit = any(c.isdigit() for c in input_value)
        return 6 <= len(input_value) <= 20 and has_lower and has_digit
    elif input_type == "email":
        # 邮箱规则:包含@和.,且@在.之前,避免非法格式(如"a@b"、"a.b@c")
        if "@" not in input_value or "." not in input_value:
            return False
        at_index = input_value.index("@")
        dot_index = input_value.rindex(".")
        return at_index < dot_index and at_index > 0 and dot_index < len(input_value) - 1
    elif input_type == "course_name":
        # 课程名规则:2-50位,可包含字母、数字、空格、短横线(如"Python OOP - 2024")
        return 2 <= len(input_value) <= 50
    elif input_type == "assignment_title":
        # 作业标题规则:2-100位,支持常见字符(如"OOP 实验三:继承与封装")
        return 2 <= len(input_value) <= 100
    else:
        return False  # 不支持的输入类型直接判定为无效


def format_date(date_str: str, target_format: str = "%Y-%m-%d") -> str | None:
    """
    日期格式处理工具(适配作业截止日期、课程开始/结束日期等场景)
    功能:将输入的日期字符串转为指定格式,或验证日期合法性,符合项目"进度追踪"与"作业管理"模块的时间数据需求
    参数:
        date_str: 待处理的日期字符串(支持"YYYY-MM-DD"、"YYYY/MM/DD"、"MM-DD-YYYY"格式)
        target_format: 目标日期格式(默认"%Y-%m-%d",即"年-月-日")
    返回:
        str | None: 格式正确返回目标格式字符串,错误返回None
    """
    # 支持的输入日期格式列表
    input_formats = ["%Y-%m-%d", "%Y/%m/%d", "%m-%d-%Y", "%m/%d/%Y"]
    for fmt in input_formats:
        try:
            # 解析输入日期并转为目标格式
            date_obj = datetime.strptime(date_str, fmt)
            return date_obj.strftime(target_format)
        except ValueError:
            continue  # 解析失败则尝试下一种格式
    return None  # 所有格式均解析失败,返回None


def calculate_average_score(scores: list[float | int]) -> float | None:
    """
    平均分计算工具(适配学生课程总成绩、作业平均分等场景)
    功能:安全计算数值列表的平均值,自动过滤无效数据,符合项目"Assignment and Grading"模块的成绩统计需求
    参数:
        scores: 成绩列表(元素为合法数字或可转为数字的类型)
    返回:
        float | None: 计算成功返回平均分(保留1位小数),无有效成绩返回None
    """
    valid_scores = []
    for score in scores:
        try:
            # 尝试将元素转为float,过滤非数字数据
            num_score = float(score)
            # 成绩范围约束(0-100分,符合常规评分逻辑)
            if 0 <= num_score <= 100:
                valid_scores.append(num_score)
        except (ValueError, TypeError):
            continue  # 跳过无法转为数字的元素
    # 无有效成绩返回None,否则计算平均分
    return round(sum(valid_scores) / len(valid_scores), 1) if valid_scores else None


def check_enrollment_eligibility(student_enrolled_courses: list, target_course: object, max_courses_per_student: int = 5) -> tuple[bool, str]:
    """
    选课资格验证工具(适配"Enrollment System"模块,确保学生选课合规)
    功能:验证学生是否符合选课条件(如未超选课上限、未重复选课、课程未满员),符合项目"Course Management"的约束需求
    参数:
        student_enrolled_courses: 学生已选课程列表(元素为Course类实例)
        target_course: 目标选课的Course类实例(需包含enrolled_students属性、max_students属性)
        max_courses_per_student: 学生最大选课数(默认5门,可配置)
    返回:
        tuple[bool, str]: (验证结果, 结果说明),成功为(True, "可选课"),失败为(False, "失败原因")
    """
    # 1. 验证是否重复选课
    if target_course in student_enrolled_courses:
        return False, "已选该课程,无需重复选择"
    # 2. 验证学生是否超选课上限
    if len(student_enrolled_courses) >= max_courses_per_student:
        return False, f"已达最大选课数({max_courses_per_student}门),无法继续选课"
    # 3. 验证目标课程是否满员
    if len(target_course.enrolled_students) >= target_course.max_students:
        return False, f"目标课程已满员(上限{target_course.max_students}人),无法选课"
    # 所有条件均满足,返回成功
    return True, "选课资格验证通过"